package cinvestment;

import java.awt.font.TextMeasurer;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.math.BigDecimal;
import java.sql.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import maxflow.MaxFlow;
import support.AlgorithmSupport;
import util.Lang;
import util.MathUtil;

public class Main {
	private static int simulationCount = 10000;

	public static void main(String[] args) {

		// lshapedMultiCuts();

		// lshapedSingleCut();

		// lshapedNoFixedConcurrent();
		lshapedNoFixed();
		// lshapedExample();
		// lshapedFixedConcurrent();
		// lshapedFixedMulticut();
		// lshapedNoFixedMulticut();
		// gradientNoFixed();

		// String[] structures = { AlgorithmSupport.CHAINING,
		// AlgorithmSupport.W_SHAPE };
		// double[] c1 = new double[1];
		// double[] c1 = { 0.25 };
		// for (int i = 0; i < c1.length; i++) {
		// c1[i] = BigDecimal
		// .valueOf(0.2)
		// .add(BigDecimal.valueOf(0.4)
		// .multiply(BigDecimal.valueOf(i))).doubleValue();
		// }
		// c1[0] = 0.25;
		// double[] penalties = new double[5];
		// for (int i = 0; i < penalties.length; i++) {
		// penalties[i] = BigDecimal
		// .valueOf(1.0)
		// .add(BigDecimal.valueOf(0.2)
		// .multiply(BigDecimal.valueOf(i))).doubleValue();
		// }
		// double[] s_ratios = { 0.0, 0.0005, 0.005, 0.05, 0.07, 0.08, 0.09,
		// 0.1,
		// 0.15, 0.2 };
		// double[] s_ratios = { 0.0 };
		// double[] deltas = new double[10];
		// for (int i = 0; i < deltas.length; i++) {
		// deltas[i] = BigDecimal.valueOf(0.01)
		// .add(BigDecimal.valueOf(0.01 * i)).doubleValue();
		// }
		//
		// double[] variances = { 0.3 };
		//
		// for (String structure : structures) {
		// // lshapedNoFixedMulticut_penalty(c1, penalties, s_ratios, 0.25,
		// // structure);
		// for (double variance : variances) {
		// lshapedNoFixedMulticut_fixed(c1, 1.0, s_ratios, 0.25,
		// structure, variance);
		//
		// }
		// }

		// for (int N = 10; N < 20; N++) {
		// System.out.println("########## " + N + " ###########");
		// double total = testMaxFlow(AlgorithmSupport.TOTAL_FLEXIBILITY, N);
		// double lc = testMaxFlow(AlgorithmSupport.CHAINING, N);
		// double w = testMaxFlow(AlgorithmSupport.W_SHAPE, N);
		// double uc = testMaxFlow(AlgorithmSupport.UNBALANCE_CHAIN, N);
		//
		// double rlc = BigDecimal
		// .valueOf(lc)
		// .divide(BigDecimal.valueOf(total), 5,
		// BigDecimal.ROUND_HALF_EVEN).doubleValue();
		// double rw = BigDecimal
		// .valueOf(w)
		// .divide(BigDecimal.valueOf(total), 5,
		// BigDecimal.ROUND_HALF_EVEN).doubleValue();
		// double ru = BigDecimal
		// .valueOf(uc)
		// .divide(BigDecimal.valueOf(total), 5,
		// BigDecimal.ROUND_HALF_EVEN).doubleValue();
		//
		// System.out.println("@result of "
		// + AlgorithmSupport.TOTAL_FLEXIBILITY + ": " + total);
		// System.out.println("@result of " + AlgorithmSupport.CHAINING + ": "
		// + lc + "; ratio=" + rlc);
		// System.out.println("@result of " + AlgorithmSupport.W_SHAPE + ": "
		// + w + "; ratio=" + rw);
		// System.out.println("@result of " + AlgorithmSupport.UNBALANCE_CHAIN+
		// ": "
		// + uc + "; ratio =" + ru);
		// }

		// double[] var = { 0.3, 0.5, 0.7, 0.9 };
		// testMaxFlow_variance(AlgorithmSupport.W_SHAPE, 4, var);
	}

	private static void lshapedNoFixedMulticut_penalty(double[] c1,
			double[] penalty, double[] s_ratios, double delta, String structure) {
		int N = 4;

		String path = Lang.projectRoot() + "\\data\\result\\20141027\\penalty_"
				+ structure + N + "_" + Lang.DATE_FORMAT.format(new Date())
				+ ".xlsx";
		for (int rc = 0; rc < s_ratios.length; rc++) {
			String sheetName = String.valueOf(s_ratios[rc]);
			List<List<Double[]>> outputData = new ArrayList<>();
			long start = System.currentTimeMillis();

			for (int pc = 0; pc < penalty.length; pc++) {
				double[] penalties = new double[N];
				for (int i = 0; i < N; i++)
					penalties[i] = penalty[pc];
				CapacityInvestmentMultiCut cim = new CapacityInvestmentMultiCut(
						delta, N, simulationCount, penalties, c1[0],
						s_ratios[rc]);
				cim.setStructure(structure);
				cim.setVarianceDemand(0.95);
				List<Double[]> result = cim.lshaped();
				outputData.add(result);
			}
			// output results
			List<Plant> plants = AlgorithmSupport.createPlantsByStructure(N,
					structure);
			List<String> headTitle = new ArrayList<>();
			for (Plant plant : plants) {
				String s = plant.getAvailableProducts().toString();
				headTitle.add(s);
			}

			long time = System.currentTimeMillis() - start;
			List<String> simulationInfo = new ArrayList<>();
			simulationInfo.add("investigate penalty effects");
			simulationInfo.add("no fixed cost && multicut && " + structure);
			simulationInfo.add("productTypes = " + N);
			simulationInfo.add("simulationCount = " + simulationCount);
			simulationInfo.add("delta = " + delta);
			simulationInfo.add("penalties.ratio = " + Arrays.toString(penalty));
			simulationInfo.add("fixed_ratios = " + s_ratios[rc]);
			simulationInfo.add("c1=" + Arrays.toString(c1));
			simulationInfo.add("time consumed = " + time);
			double[] deltas = { delta };
			AlgorithmSupport.storeFinalResult(path, sheetName, outputData,
					deltas, headTitle, simulationInfo, N);
		}

	}

	private static void lshapedNoFixedMulticut_fixed(double[] c1,
			double penalty, double[] s_ratio, double delta, String structure,
			double variance) {
		int N = 4;
		String path = Lang.projectRoot() + "\\data\\result\\20141105\\fixed_"
				+ structure + N + "_" + variance + "_"
				+ Lang.DATE_FORMAT.format(new Date()) + ".xlsx";
		for (int cc = 0; cc < c1.length; cc++) {
			String sheetName = String.valueOf(c1[cc]);
			List<List<Double[]>> outputData = new ArrayList<>();
			long start = System.currentTimeMillis();

			double[] penaltiesVa = { 0.6, 0.8, 1.0, 1.2, 1.4 };
			for (int pc = 0; pc < penaltiesVa.length; pc++) {
				for (int sc = 0; sc < s_ratio.length; sc++) {
					double[] penalties = new double[N];
					for (int i = 0; i < N; i++)
						penalties[i] = penaltiesVa[pc];
					// double[] penalties = { 1.0, 0.5, 0.5, 1.0 };
					CapacityInvestmentMultiCut cim = new CapacityInvestmentMultiCut(
							delta, N, simulationCount, penalties, c1[cc],
							s_ratio[sc]);
					cim.setStructure(structure);
					cim.setVarianceDemand(variance);
					List<Double[]> result = cim.lshaped();

					outputData.add(result);
				}
			}
			// output results
			List<Plant> plants = AlgorithmSupport.createPlantsByStructure(N,
					structure);
			List<String> headTitle = new ArrayList<>();
			for (Plant plant : plants) {
				String s = plant.getAvailableProducts().toString();
				headTitle.add(s);
			}

			long time = System.currentTimeMillis() - start;
			List<String> simulationInfo = new ArrayList<>();
			simulationInfo.add("investigate fixed cost normal distribution");
			simulationInfo.add("no fixed cost && multicut && " + structure);
			simulationInfo.add("productTypes = " + N);
			simulationInfo.add("simulationCount = " + simulationCount);
			simulationInfo.add("delta = " + delta);
			simulationInfo.add("penalties = " + penalty);
			simulationInfo.add("fixed_ratios = " + Arrays.toString(s_ratio));
			simulationInfo.add("c1=" + c1[cc]);
			simulationInfo.add("time consumed = " + time);
			double[] deltas = { delta };
			AlgorithmSupport.storeFinalResult(path, sheetName, outputData,
					deltas, headTitle, simulationInfo, N);
		}

	}

	/**
	 * solve the problem using multi cuts L-shaped method
	 * **/
	private static void lshapedMultiCuts() {
		CapacityInvestment cin = new CapacityInvestment();
		cin.lshapedCalculate();
	}

	/**
	 * solve the problem using single cut L-shaped method
	 * **/
	private static void lshapedSingleCut() {
		// double[] delta = { 0.007, 0.01, 0.02, 0.03, 0.04, 0.06, 0.08, 0.1,
		// 0.12 };
		double[] delta = { 0.25 };
		int[] productTypes = { 5 };
		int simulationCount = 5000;
		double c1 = 0.25;
		long start = System.currentTimeMillis();
		for (int pt = 0; pt < productTypes.length; pt++) {
			List<List<Double[]>> outputData = new ArrayList<>();
			double[] penalties = new double[productTypes[pt]];
			for (int i = 0; i < productTypes[pt]; i++)
				penalties[i] = 1.0;
			double[] ratios = { 0.0, 0.02, 0.04, 0.1, 0.2, 0.5, 0.6, 0.8 };
			// double[] ratios = { 1.0 };

			for (int i = 0; i < delta.length; i++) {
				for (int j = 0; j < ratios.length; j++) {
					CapacityInvestmentSingleCut ct = new CapacityInvestmentSingleCut(
							delta[i], productTypes[pt], simulationCount,
							penalties, c1, ratios[j]);
					List<Double[]> result = ct.lshapedCalculate();
					outputData.add(result);
				}
			}

			// output results
			List<List<Integer>> plantsSet = MathUtil.subSetOrder(MathUtil
					.getSetFromZ(productTypes[pt]));
			List<String> headTitle = new ArrayList<>();
			for (List<Integer> plant : plantsSet) {
				String s = Arrays.toString(Lang.conver2Array(plant));
				headTitle.add(s);
			}
			List<String> simulationInfo = new ArrayList<>();
			simulationInfo.add("Considering fixed cost");
			simulationInfo.add("productTypes = " + productTypes);
			simulationInfo.add("simulationCount = " + simulationCount);
			simulationInfo.add("delta = " + Arrays.toString(delta));
			simulationInfo.add("penalties = " + Arrays.toString(penalties));
			simulationInfo.add("c1=" + c1);
			simulationInfo.add("ratio = " + Arrays.toString(ratios));

			String path = Lang.projectRoot()
					+ "\\data\\result\\20141201\\singleCutFixed_"
					+ productTypes + "_" + Lang.DATE_FORMAT.format(new Date())
					+ ".xlsx";

			AlgorithmSupport.storeFinalResult(path, "result", outputData,
					delta, headTitle, simulationInfo, productTypes[pt]);
		}

		long time = System.currentTimeMillis() - start;
		System.out.println("con time = " + time);
	}

	private static void lshapedExample() {
		Example example = new Example();
		example.lShapedExample();
	}

	private static void lshapedNoFixed() {
		// double[] delta = { 0.001, 0.007, 0.01, 0.02, 0.04, 0.08, 0.1, 0.12 };
		double[] delta = { 0.25 };
		// double[] delta = new double[15];
		// double[] delta = { 0, 0.00001, 0.0001, 0.0005, 0.001, 0.002, 0.01,
		// 0.02, 0.03, 0.04, 0.06, 0.08, 0.09, 0.10, 0.11, 0.12 };
		double d1 = 0.01;
		double[] cList = new double[1];
		double c = 0.25;
		// for (int i = 1; i <= 15; i++) {
		// delta[i - 1] = d1 * i;
		// }

		// for (int i = 8; i < 9; i++) {
		// cList[0] = BigDecimal
		// .valueOf(c)
		// .add(BigDecimal.valueOf(0.1)
		// .multiply(BigDecimal.valueOf(i))).doubleValue();
		// }
		cList[0] = c;

		int[] productTypes = { 10 };
		int simulationCount = 5000;
		// double c1 = 0.5;
		List<List<Double[]>> outputData = new ArrayList<>();
		long start = System.currentTimeMillis();
		for (int ty = 0; ty < productTypes.length; ty++) {
			double[] penalties = new double[productTypes[ty]];
			for (int i = 0; i < productTypes[ty]; i++)
				penalties[i] = 1;

			String path = Lang.projectRoot()
					+ "\\data\\result\\20141201\\result_" + productTypes[ty]
					+ "_" + Lang.DATE_FORMAT.format(new Date()) + ".xlsx";

			for (int j = 0; j < cList.length; j++) {
				outputData = new ArrayList<>();
				String sheetName = "result_" + cList[j];
				for (int i = 0; i < delta.length; i++) {
					CapacityInvestmentNoFixed ct = new CapacityInvestmentNoFixed(
							delta[i], productTypes[ty], simulationCount,
							penalties, cList[j]);
					List<Double[]> result = ct.lshapedCalculate();

					outputData.add(result);
				}
				// output results
				List<List<Integer>> plantsSet = MathUtil.subSetOrder(MathUtil
						.getSetFromZ(productTypes[ty]));
				List<String> headTitle = new ArrayList<>();
				for (List<Integer> plant : plantsSet) {
					String s = Arrays.toString(Lang.conver2Array(plant));
					headTitle.add(s);
				}
				List<String> simulationInfo = new ArrayList<>();
				simulationInfo.add("No fixed cost");
				simulationInfo.add("productTypes = " + productTypes[ty]);
				simulationInfo.add("simulationCount = " + simulationCount);
				simulationInfo.add("delta = " + Arrays.toString(delta));
				simulationInfo.add("penalties = " + Arrays.toString(penalties));
				simulationInfo.add("c1=" + cList[j]);

				AlgorithmSupport.storeFinalResult(path, sheetName, outputData,
						delta, headTitle, simulationInfo, productTypes[ty]);

				try {
					Writer writer = new BufferedWriter(new FileWriter(
							Lang.projectRoot() + "\\data\\result\\record.txt",
							true));
					writer.write(Lang.DATE_FORMAT.format(new Date()) + ":\t j="
							+ j + "\r\n");
					writer.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		}
		long time = System.currentTimeMillis() - start;
		System.out.println("con time = " + time);
	}

	private static void lshapedNoFixedConcurrent() {
		// double[] delta = { 0.001, 0.007, 0.01, 0.02, 0.04, 0.08, 0.1, 0.12 };
		double[] delta = { 0.1 };
		// double[] delta = new double[15];
		// double[] delta = { 0, 0.00001, 0.0001, 0.0005, 0.001, 0.002, 0.01,
		// 0.02, 0.03, 0.04, 0.06, 0.08, 0.09, 0.10, 0.11, 0.12 };
		double d1 = 0.01;
		double[] cList = new double[1];
		double c = 0.1;
		// delta[0] = 0.000001;
		// for (int i = 1; i < 15; i++) {
		// delta[i] = d1 * i;
		// }

		for (int i = 8; i < 9; i++) {
			cList[0] = BigDecimal
					.valueOf(c)
					.add(BigDecimal.valueOf(0.1)
							.multiply(BigDecimal.valueOf(i))).doubleValue();
		}

		int[] productTypes = { 4 };
		int simulationCount = 10000;
		// double c1 = 0.5;
		List<List<Double[]>> outputData = new ArrayList<>();
		long start = System.currentTimeMillis();
		for (int ty = 0; ty < productTypes.length; ty++) {

			double[] penalties = new double[productTypes[ty]];
			for (int i = 0; i < productTypes[ty]; i++)
				penalties[i] = 1;

			String path = Lang.projectRoot() + "\\data\\result\\result_conc_"
					+ productTypes[ty] + "_"
					+ Lang.DATE_FORMAT.format(new Date()) + ".xlsx";

			for (int j = 0; j < cList.length; j++) {
				outputData = new ArrayList<>();
				String sheetName = "result_" + cList[j];
				for (int i = 0; i < delta.length; i++) {
					// CapacityInvestmentConcurrent cic = new
					// CapacityInvestmentConcurrent(
					// delta[i], productTypes[ty], simulationCount,
					// penalties, cList[j]);
					// List<Double[]> result = cic.lshaped();
					CapacityInvestmentGradient cig = new CapacityInvestmentGradient(
							delta[i], productTypes[ty], simulationCount,
							penalties, cList[j]);
					List<Double[]> result = cig.lshape();
					outputData.add(result);
				}
				// output results
				List<List<Integer>> plantsSet = MathUtil.subSetOrder(MathUtil
						.getSetFromZ(productTypes[ty]));
				List<String> headTitle = new ArrayList<>();
				for (List<Integer> plant : plantsSet) {
					String s = Arrays.toString(Lang.conver2Array(plant));
					headTitle.add(s);
				}
				List<String> simulationInfo = new ArrayList<>();
				simulationInfo.add("No fixed cost");
				simulationInfo.add("productTypes = " + productTypes[ty]);
				simulationInfo.add("simulationCount = " + simulationCount);
				simulationInfo.add("delta = " + Arrays.toString(delta));
				simulationInfo.add("penalties = " + Arrays.toString(penalties));
				simulationInfo.add("c1=" + cList[j]);

				AlgorithmSupport.storeFinalResult(path, sheetName, outputData,
						delta, headTitle, simulationInfo, productTypes[ty]);

				try {
					Writer writer = new BufferedWriter(new FileWriter(
							Lang.projectRoot() + "\\data\\result\\record.txt",
							true));
					writer.write(Lang.DATE_FORMAT.format(new Date()) + ":\t j="
							+ j + "\r\n");
					writer.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		long time = System.currentTimeMillis() - start;
		System.out.println("con time = " + time);
	}

	private static void lshapedFixedConcurrent() {
		double[] delta = { 0.25 };
		double[] cList = new double[1];
		double c = 0.25;
		cList[0] = c;
		// double[] ratios = { 0.0, 0.02, 0.04, 0.1, 0.2, 0.5, 0.6, 0.8 };
		double[] ratios = { 0.02 };

		int[] productTypes = { 6 };
		int simulationCount = 5000;
		List<List<Double[]>> outputData = new ArrayList<>();
		long start = System.currentTimeMillis();
		for (int ty = 0; ty < productTypes.length; ty++) {
			double[] penalties = new double[productTypes[ty]];
			for (int i = 0; i < productTypes[ty]; i++)
				penalties[i] = 1;

			String path = Lang.projectRoot()
					+ "\\data\\result\\singleCutFixed_conc_" + productTypes[ty]
					+ "_" + Lang.DATE_FORMAT.format(new Date()) + ".xlsx";

			for (int j = 0; j < cList.length; j++) {
				outputData = new ArrayList<>();
				String sheetName = "result_" + cList[j];
				for (int i = 0; i < delta.length; i++) {
					for (int k = 0; k < ratios.length; k++) {
						CapacityInvestmentConWithFixed cig = new CapacityInvestmentConWithFixed(
								delta[i], productTypes[ty], simulationCount,
								penalties, cList[j], ratios[k]);
						List<Double[]> result = cig.Lshape();
						outputData.add(result);
					}
				}
				// output results
				List<List<Integer>> plantsSet = MathUtil.subSetOrder(MathUtil
						.getSetFromZ(productTypes[ty]));
				List<String> headTitle = new ArrayList<>();
				for (List<Integer> plant : plantsSet) {
					String s = Arrays.toString(Lang.conver2Array(plant));
					headTitle.add(s);
				}
				List<String> simulationInfo = new ArrayList<>();
				simulationInfo.add("with fixed cost");
				simulationInfo.add("productTypes = " + productTypes[ty]);
				simulationInfo.add("simulationCount = " + simulationCount);
				simulationInfo.add("delta = " + Arrays.toString(delta));
				simulationInfo.add("penalties = " + Arrays.toString(penalties));
				simulationInfo.add("c1=" + cList[j]);
				simulationInfo.add("ratio = " + Arrays.toString(ratios));

				AlgorithmSupport.storeFinalResult(path, sheetName, outputData,
						delta, headTitle, simulationInfo, productTypes[ty]);

				try {
					Writer writer = new BufferedWriter(new FileWriter(
							Lang.projectRoot() + "\\data\\result\\record.txt",
							true));
					writer.write(Lang.DATE_FORMAT.format(new Date()) + ":\t j="
							+ j + "\r\n");
					writer.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		long time = System.currentTimeMillis() - start;
		System.out.println("con time = " + time);
	}

	private static void lshapedFixedMulticut() {
		double delta = 0.25;
		double c = 0.25;
		// double[] ratios = { 0.0, 0.02, 0.04, 0.1, 0.2, 0.5, 0.6, 0.8, 0.9,
		// 1.0,
		// 1.1, 1.2, 1.3, 1.4, 1.5 };
		// double[] ratios = { 0.005, 0.01, 0.04, 0.1, 0.2, 0.3, 0.5 };
		double[] ratios = { 0.03 };

		int[] productTypes = { 6 };
		int simulationCount = 5000;

		List<List<Double[]>> outputData = new ArrayList<>();

		for (int ty = 0; ty < productTypes.length; ty++) {
			long start = System.currentTimeMillis();

			double[] penalties = new double[productTypes[ty]];
			for (int i = 0; i < productTypes[ty]; i++)
				penalties[i] = 1;

			String path = Lang.projectRoot()
					+ "\\data\\result\\20141202\\multicut_fixed_"
					+ productTypes[ty] + "_"
					+ Lang.DATE_FORMAT.format(new Date()) + ".xlsx";

			outputData = new ArrayList<>();
			String sheetName = "result";
			for (int i = 0; i < ratios.length; i++) {
				CapacityInvestmentMultiCut cigmc = new CapacityInvestmentMultiCut(
						delta, productTypes[ty], simulationCount, penalties, c,
						ratios[i]);
				List<Double[]> result = cigmc.lshaped();
				outputData.add(result);
			}
			// output results
			List<List<Integer>> plantsSet = MathUtil.subSetOrder(MathUtil
					.getSetFromZ(productTypes[ty]));
			List<String> headTitle = new ArrayList<>();
			for (List<Integer> plant : plantsSet) {
				String s = Arrays.toString(Lang.conver2Array(plant));
				headTitle.add(s);
			}

			long time = System.currentTimeMillis() - start;

			List<String> simulationInfo = new ArrayList<>();
			simulationInfo.add("fixed cost && multicut");
			simulationInfo.add("productTypes = " + productTypes[ty]);
			simulationInfo.add("simulationCount = " + simulationCount);
			simulationInfo.add("delta = " + delta);
			simulationInfo.add("penalties = " + Arrays.toString(penalties));
			simulationInfo.add("ratios = " + Arrays.toString(ratios));
			simulationInfo.add("c1=" + c);
			simulationInfo.add("time consumed = " + time);
			simulationInfo
					.add("with elpsilon adjustment, and relax binary to linear ");

			double[] deltas = { delta };
			AlgorithmSupport.storeFinalResult(path, sheetName, outputData,
					deltas, headTitle, simulationInfo, productTypes[ty]);

			try {
				Writer writer = new BufferedWriter(
						new FileWriter(Lang.projectRoot()
								+ "\\data\\result\\record.txt", true));
				writer.write(Lang.DATE_FORMAT.format(new Date()) + "\r\n");
				writer.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	private static void lshapedNoFixedMulticut() {
		double c = 0.25;
		double[] cs = new double[8];
		cs[0] = 0.20;
		for (int i = 1; i < 8; i++)
			cs[i] = BigDecimal.valueOf(cs[i - 1]).add(BigDecimal.valueOf(0.1))
					.doubleValue();
		double[] ratios_penalty = { 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };

		double[] ratios = new double[1];
		ratios[0] = 0.25;
		// ratios[1] = 1.5;
		// for (int i = 2; i < 11; i++)
		// ratios[i] = BigDecimal.valueOf(ratios[i - 2])
		// .add(BigDecimal.valueOf(ratios[i - 1])).doubleValue();
		// double[] ratios = { 0.1 };
		// double[] deltas = { 0, 0.001, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06,
		// 0.08,
		// 0.09, 0.1, 0.12 };
		double[] deltas = { 0.25 };
		double[] penalties_para = new double[10];
		penalties_para[0] = 0.1;
		for (int i = 1; i < penalties_para.length; i++)
			penalties_para[i] = BigDecimal.valueOf(penalties_para[i - 1])
					.add(BigDecimal.valueOf(0.1)).doubleValue();

		int[] productTypes = { 4 };
		int simulationCount = 10000;

		List<List<Double[]>> outputData = new ArrayList<>();

		for (int ty = 0; ty < productTypes.length; ty++) {
			String path = Lang.projectRoot()
					+ "\\data\\result\\multicut_pairing_" + productTypes[ty]
					+ "_" + Lang.DATE_FORMAT.format(new Date()) + ".xlsx";
			for (int cc = 0; cc < cs.length; cc++) {
				long start = System.currentTimeMillis();

				outputData = new ArrayList<>();
				String sheetName = String.valueOf(cs[cc]);
				for (int i = 0; i < ratios_penalty.length; i++) {
					double[] penalties = new double[productTypes[ty]];
					double pen = BigDecimal.valueOf(cs[cc])
							.multiply(BigDecimal.valueOf(ratios_penalty[i]))
							.doubleValue();
					for (int pt = 0; pt < productTypes[ty]; pt++)
						penalties[pt] = pen;

					CapacityInvestmentMultiCut cigmc = new CapacityInvestmentMultiCut(
							deltas[0], productTypes[ty], simulationCount,
							penalties, c, ratios[0]);
					List<Double[]> result = cigmc.lshaped();
					outputData.add(result);
				}
				// output results
				List<List<Integer>> plantsSet = MathUtil.subSetOrder(MathUtil
						.getSetFromZ(productTypes[ty]));
				List<String> headTitle = new ArrayList<>();
				for (List<Integer> plant : plantsSet) {
					String s = Arrays.toString(Lang.conver2Array(plant));
					headTitle.add(s);
				}

				long time = System.currentTimeMillis() - start;

				List<String> simulationInfo = new ArrayList<>();
				simulationInfo.add("no fixed cost && multicut && pairing");
				simulationInfo.add("productTypes = " + productTypes[ty]);
				simulationInfo.add("simulationCount = " + simulationCount);
				simulationInfo.add("delta = " + Arrays.toString(deltas));
				simulationInfo.add("penalties.ratio = "
						+ Arrays.toString(ratios_penalty));
				simulationInfo.add("ratios = " + Arrays.toString(ratios));
				simulationInfo.add("c1=" + c);
				simulationInfo.add("time consumed = " + time);

				AlgorithmSupport.storeFinalResult(path, sheetName, outputData,
						deltas, headTitle, simulationInfo, productTypes[ty]);
			}
		}

	}

	private static void gradientNoFixed() {
		double c = 0.25;
		double[] cs = new double[20];
		cs[0] = 0.10;
		for (int i = 1; i < 20; i++)
			cs[i] = BigDecimal.valueOf(cs[i - 1]).add(BigDecimal.valueOf(0.05))
					.doubleValue();

		double[] ratios = new double[2];
		ratios[0] = 0.1;
		ratios[1] = 1.5;
		double[] deltas = { 0.25 };
		double[] penalties_para = new double[10];
		penalties_para[0] = 0.1;
		for (int i = 1; i < penalties_para.length; i++)
			penalties_para[i] = BigDecimal.valueOf(penalties_para[i - 1])
					.add(BigDecimal.valueOf(0.1)).doubleValue();

		int[] productTypes = { 4 };
		int simulationCount = 10000;

		List<List<Double[]>> outputData = new ArrayList<>();

		for (int ty = 0; ty < productTypes.length; ty++) {
			String path = Lang.projectRoot()
					+ "\\data\\result\\gradient_wshape_" + productTypes[ty]
					+ "_" + Lang.DATE_FORMAT.format(new Date()) + ".xlsx";
			for (int pc = 0; pc < penalties_para.length; pc++) {
				long start = System.currentTimeMillis();

				double[] penalties = new double[productTypes[ty]];
				for (int i = 0; i < productTypes[ty]; i++)
					penalties[i] = penalties_para[pc];

				outputData = new ArrayList<>();
				String sheetName = String.valueOf(penalties_para[pc]);
				for (int i = 0; i < ratios.length; i++) {
					CapacityInvestmentGradient cig = new CapacityInvestmentGradient(
							deltas[0], productTypes[ty], simulationCount,
							penalties, c);
					List<Double[]> result = cig.lshape();
					outputData.add(result);
				}
				// output results
				List<List<Integer>> plantsSet = MathUtil.subSetOrder(MathUtil
						.getSetFromZ(productTypes[ty]));
				List<String> headTitle = new ArrayList<>();
				for (List<Integer> plant : plantsSet) {
					String s = Arrays.toString(Lang.conver2Array(plant));
					headTitle.add(s);
				}

				long time = System.currentTimeMillis() - start;

				List<String> simulationInfo = new ArrayList<>();
				simulationInfo.add("no fixed cost && gradient && wshape");
				simulationInfo.add("productTypes = " + productTypes[ty]);
				simulationInfo.add("simulationCount = " + simulationCount);
				simulationInfo.add("delta = " + Arrays.toString(deltas));
				simulationInfo.add("penalties = " + Arrays.toString(penalties));
				simulationInfo.add("ratios = " + Arrays.toString(ratios));
				simulationInfo.add("c1=" + c);
				simulationInfo.add("time consumed = " + time);

				AlgorithmSupport.storeFinalResult(path, sheetName, outputData,
						deltas, headTitle, simulationInfo, productTypes[ty]);
			}
		}
	}

	private static double testMaxFlow(String structure, int N) {
		MaxFlow mf = new MaxFlow(N, simulationCount, structure);
		mf.setVariance(0.5);
		return mf.getExpectedMaxFlow();
	}

	private static void testMaxFlow_variance(String structure, int N,
			double[] var) {
		double[] caps = { 1.533, 0.933, 1.533 };
		for (int i = 0; i < var.length; i++) {
			MaxFlow bmf = new MaxFlow(N, simulationCount, structure);
			bmf.setVariance(var[i]);
			double bre = bmf.getExpectedMaxFlow();
			System.out.println("@ balanced capacities, result = " + bre);
			MaxFlow ubmf = new MaxFlow(N, simulationCount, structure);
			ubmf.setCapacities(caps);
			ubmf.setVariance(var[i]);
			double ubre = ubmf.getExpectedMaxFlow();
			System.out.println("@ unbalaned capacities, result = " + ubre);
		}
	}
}
